/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
 */

package com.jinhe.tss.component.dynproperty;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;

import com.jinhe.tss.component.dynproperty.entity.DynableEntity;
import com.jinhe.tss.component.dynproperty.entity.GridTemplate;
import com.jinhe.tss.component.dynproperty.entity.PropertyDef;
import com.jinhe.tss.component.dynproperty.entity.PropertyTab;
import com.jinhe.tss.component.dynproperty.entity.XFormTemplate;
import com.jinhe.tss.component.dynproperty.entity.XFormTemplateTab;
import com.jinhe.tss.core.cachepool.CacheManager;
import com.jinhe.tss.core.cachepool.Cacheable;
import com.jinhe.tss.core.cachepool.IPool;
import com.jinhe.tss.core.cachepool.strategy.CacheConstants;
import com.jinhe.tss.core.exception.BusinessException;
import com.jinhe.tss.core.persistence.IEntity;
import com.jinhe.tss.core.util.BeanUtil;
import com.jinhe.tss.core.util.XMLDocUtil;

public class PropertyServiceImpl implements PropertyService {

    @Autowired private PropertyDao dao;
    
    public List<?> getDynableEntities(boolean isOnlyGroup) {
        if(isOnlyGroup) {
            return dao.getEntities("from DynableEntity o where o.entityCode is null order by o.id");
        }
        
        List<?> entities = dao.getEntities("from DynableEntity o order by o.id");
        List<?> properties = dao.getEntities("select o from PropertyDef o order by o.seqNo");
        List<?> xformTemplates = dao.getEntities("from XFormTemplate o ");
        List<?> tabs = dao.getEntities("from XFormTemplateTab o ");
        List<?> gridTemplates = dao.getEntities("from GridTemplate o");
        
        Map<String, DynableEntity> entityMap = new HashMap<String, DynableEntity>();
        Map<Long, XFormTemplate> xformTemplateMap = new HashMap<Long, XFormTemplate>();
        for(Iterator<?> it = entities.iterator(); it.hasNext(); ){
            DynableEntity entity = (DynableEntity) it.next();
            //判断是否是实体组
            if(!entity.isGroup()){ entityMap.put(entity.getEntityCode(), entity); }
        }
        for(Iterator<?> it = properties.iterator(); it.hasNext(); ){
            PropertyDef property = (PropertyDef) it.next();
            ((DynableEntity)entityMap.get(property.getEntityCode())).getProperties().add(property);
        }
        for(Iterator<?> it = xformTemplates.iterator(); it.hasNext(); ){
            XFormTemplate template = (XFormTemplate) it.next();
            xformTemplateMap.put(template.getId(), template);
            ((DynableEntity)entityMap.get(template.getEntityCode())).getXformTemplates().add(template);
        }
        for(Iterator<?> it = gridTemplates.iterator(); it.hasNext(); ){
            GridTemplate template = (GridTemplate) it.next();
            ((DynableEntity)entityMap.get(template.getEntityCode())).getGridTemplates().add(template);
        }
        for(Iterator<?> it = tabs.iterator(); it.hasNext(); ){
            XFormTemplateTab tab = (XFormTemplateTab) it.next();
            ((XFormTemplate)xformTemplateMap.get(tab.getXformTemplateId())).getTabs().add(tab);
        }
        return entities;
    }

    public DynableEntity getGroupOrEntityById(Long id) {
        return (DynableEntity) dao.getEntity(DynableEntity.class, id);
    }

    public DynableEntity saveGroup(DynableEntity group) {
        if(group.getId() == null)
            group.setSeqNo(dao.getNextOrderByPId(group.getParentId()));
        return (DynableEntity) dao.create(group);
    }

    public void deleteGroupOrEntity(Long id) {
        DynableEntity obj = getGroupOrEntityById(id);
        if(obj.isGroup()){
            List<?> sons = dao.getEntities("select o.id from DynableEntity o where o.parentId = ?", id);
            for(Iterator<?> it = sons.iterator(); it.hasNext();){
                Long childId = (Long) it.next();
                moveGroupOrEntity(childId, DynableEntity.DYN_ROOT_ID);
            }
            dao.delete(obj);
        }
        else {
            this.deleteDynableEntity(obj.getEntityCode());
        }
    }
    
    public List<?> getCanMoveToGroups(Long id){
        return dao.getEntities("from DynableEntity o where o.entityCode is null order by o.id");
    }

    public void moveGroupOrEntity(Long id, Long targetId) {
        targetId = targetId == null ? DynableEntity.DYN_ROOT_ID : targetId;
        
        DynableEntity obj = getGroupOrEntityById(id);
        obj.setParentId(targetId);
        obj.setSeqNo(dao.getNextOrderByPId(targetId));
        dao.moveGroupOrEntity(obj);
    }

    public PropertyDef getPropertyById(Long propertyId) {
        return (PropertyDef) dao.getEntity(PropertyDef.class, propertyId);
    }

    public PropertyDef saveProperty(PropertyDef property) {
        String entityCode = property.getEntityCode();
        if(property.getId() == null){
            //新增的都为动态属性，修改的有可能是基本属性
            property.setIsdyn(new Integer(1)); 
            List<?> entities = dao.getEntities("from PropertyDef o where o.key = ? and o.entityCode = ?", property.getKey(), entityCode);
            
            if(entities != null && entities.size() > 0) {
                throw new BusinessException("EntityCode为" + entityCode + "的实体下名为 " + property.getKey() + " 的动态属性已经存在，新增失败！");
            }
            property.setSeqNo( dao.getNextSeqNo(entityCode) );
        }            
        return (PropertyDef) dao.create(property);
    }

    public void deleteProperty(Long id) {
        XFormTemplateTab tab;
        if((tab = checkPropertyInUse(id)) != null)
            throw new BusinessException("属性正被表单页：" + tab.getName() + " 使用中，删除失败!");
        
        PropertyDef property = (PropertyDef) dao.loadEntity(PropertyDef.class, id);
        
        if(!property.isdyn()){
            throw new BusinessException("属性为基本属性，非动态属性不能删除，删除失败!");
        }
        
        dao.deleteAll(dao.getEntities("from PropertyEntry o where o.defId = ?", id));
        dao.delete(property);
    }
    
    /**
     * 验证属性是否正备某个XForm模板引用到
     * @param id
     * @return
     */
    private XFormTemplateTab checkPropertyInUse(Long id){
        List<?> list = dao.getEntities("from PropertyTab o where o.id.defId = ? ", id);
        if(!list.isEmpty()){
            PropertyTab pt = (PropertyTab) list.get(0);
            return (XFormTemplateTab) dao.getEntity(XFormTemplateTab.class, pt.getId().getTabId());
        }
        return null;
    }

    public PropertyDef copyProperty(Long id) {
        PropertyDef property = (PropertyDef) dao.loadEntity(PropertyDef.class, id);
        dao.evict(property);
        property.setId(null);
        property.setIsdyn(new Integer(1));
        property.setKey("Copy_" + property.getKey());
        return  saveProperty(property);
    }

    public PropertyDef copyPropertyTo(Long id, Long targetId) {
        PropertyDef property = (PropertyDef) dao.loadEntity(PropertyDef.class, id);
        DynableEntity entity = (DynableEntity) dao.loadEntity(DynableEntity.class, targetId);
        dao.evict(property);
        property.setId(null);
        property.setIsdyn(new Integer(1));
        property.setEntityCode(entity.getEntityCode());
        property.setEntityName(entity.getName());
        return  saveProperty(property);
    }

    public void sortProperty(Long propertyId, Long targetId, int direction) {
        PropertyDef sourceItem = (PropertyDef) dao.getEntity(PropertyDef.class, propertyId);
        PropertyDef targetItem = (PropertyDef) dao.getEntity(PropertyDef.class, targetId);
        
        if(targetItem == null)
            throw new BusinessException("只能在属性之间进行排序");

        Integer seqNo1 = sourceItem.getSeqNo();
        Integer seqNo2 = targetItem.getSeqNo();
        int tag = seqNo1.compareTo(seqNo2) < 0 ? 1 : -1;

        String hql = "from PropertyDef o where o.entityCode = ? and o.seqNo > ? and o.seqNo < ?";
        String entityCode = sourceItem.getEntityCode();
        List<?> list = dao.getEntities(hql, seqNo1.compareTo(seqNo2) > 0 ? 
                new Object[] {entityCode, seqNo2, seqNo1 } : new Object[] { entityCode, seqNo1, seqNo2 });   

        for (Iterator<?> it = list.iterator(); it.hasNext();) {
            PropertyDef item = (PropertyDef) it.next();
            item.setSeqNo(item.getSeqNo() - tag);
        }
        sourceItem.setSeqNo(seqNo2 + (direction - tag) / 2);
        targetItem.setSeqNo(seqNo2 - (direction + tag) / 2);
        dao.create(sourceItem);       
    }
    
    public void saveXForm(String layoutStr){
        Element formsNode = (Element) XMLDocUtil.dataXml2Doc(layoutStr).selectSingleNode("//forms");
        String entityCode = formsNode.attributeValue("entityCode");
        String xCode = formsNode.attributeValue("code");
        XFormTemplate template = getXFormTemplateByCodeNoCache(entityCode, xCode);
        dao.evict(template);
        
        Element firstLayoutNode = (Element)formsNode.selectSingleNode("//layout");  
        Long firstTabId = Long.valueOf(firstLayoutNode.attributeValue("id"));
        
        List<?> properties = dao.getEntities("from PropertyDef o where o.entityCode = ?", entityCode);
        Map<String, PropertyDef> propertiesMap = new HashMap<String, PropertyDef>();
        List<Long> hiddenProperties = new ArrayList<Long>();
        for(Iterator<?> iter = properties.iterator(); iter.hasNext(); ){
            PropertyDef property = (PropertyDef) iter.next();
            // 如果是隐藏属性，则先将其Id存放起来
            if(property.isHidden())
                hiddenProperties.add(property.getId());
            propertiesMap.put(property.getKey(), property);
        }
        template.getTabs().clear();
        
        for(Iterator<?> it = formsNode.elementIterator("layout"); it.hasNext();){
            Element layoutNode = (Element)it.next();
            Long tabId = Long.valueOf(layoutNode.attributeValue("id"));
            XFormTemplateTab tab = (XFormTemplateTab) dao.getEntity(XFormTemplateTab.class, tabId);
            dao.evict(tab);
            StringBuffer layout = new StringBuffer();
            for(Iterator<?> iter = layoutNode.elementIterator(); iter.hasNext();){
                Element temp = (Element)iter.next();
                layout.append("\n").append(temp == null ? "" : temp.asXML());
            }
            tab.setLayout(layout.toString());
            
            //根据生成的layout设置每个属性具体为哪个tab所用
            Document doc = XMLDocUtil.dataXml2Doc("<layout>" + layout.toString() + "</layout>");
            List<?> list = doc.selectNodes("//layout/*/*/label");
            for(Iterator<?> iter = list.iterator(); iter.hasNext(); ){
                Element element = (Element) iter.next();
                String key = element.attributeValue("binding");
                PropertyDef property = (PropertyDef) propertiesMap.get(key);
                tab.getPropertyIds().add(property.getId());
            }
            
            //将隐藏属性全部放到第一个tab中（非查询表单）
            if(tabId.equals(firstTabId) && "0".equals(template.getIsQueryForm())){
                tab.getPropertyIds().addAll(hiddenProperties);
            }
            template.getTabs().add(tab);
        }
        
        saveXFormTemplate(template);
    }

    public XFormTemplate saveXFormTemplate(XFormTemplate xTemplate) {
        if(!xTemplate.getTabs().isEmpty()){
            for(Iterator<?> it = xTemplate.getTabs().iterator(); it.hasNext();){
                saveXFormTemplateTab((XFormTemplateTab) it.next(), xTemplate.getEntityCode());
            }
        }
        xTemplate = (XFormTemplate) dao.create(xTemplate);
        
        //更新缓存
        String key = xTemplate.getEntityCode() + "_" + xTemplate.getCode();
        CacheManager.getInstance().getCachePool(CacheConstants.XFORM_TEMPLATE_POOL).putObject(key, xTemplate);
        return xTemplate;
    }

    public XFormTemplateTab saveXFormTemplateTab(XFormTemplateTab tab, String entityCode) {
        //如果tab已经在数据库中存在，则先删除PropertyTab表中该tab页对应property的记录
        if(tab.getId() != null){
            dao.deleteAll( dao.getEntities("from PropertyTab o where o.id.tabId = ? ", tab.getId()) );
            dao.flush();
        }
        else {
            tab.setSeqNo(dao.getTabNextSeqNo(tab.getXformTemplateId()));
        }
        
        tab = (XFormTemplateTab) dao.create(tab);
        List<Long> propertyIds = tab.getPropertyIds();
        if(!propertyIds.isEmpty()){
            //将PropertyTab 表补齐
            //有这样的可能，属性在tab页布局中，但是属性已经被设置为了隐藏，这样的会导致propertyIds中有重复的值
            //用HashSet来消除重复的值。
            Collection<Long> c = new HashSet<Long>(propertyIds);
            for(Long propertyId : c){
                PropertyTab pt = new PropertyTab();
                pt.getId().setTabId(tab.getId());
                pt.getId().setDefId(propertyId);
                dao.create(pt);
            }
            
            //生成declare节点
            List<?> properties = dao.getEntities("from PropertyDef t where t.id in (:propertyIds)", 
                    new Object[]{"propertyIds"}, new Object[]{propertyIds.toArray()});
            
            StringBuffer sb = new StringBuffer("<xform>");
            DynableEntity entity = getDynableEntity(entityCode);
            String className = entity.getClassName();
            sb.append("<declare prefix=\"" + className.substring(className.lastIndexOf(".") + 1).toLowerCase() + "\">");
            for(Iterator<?> iter = properties.iterator(); iter.hasNext();){
                PropertyDef property = (PropertyDef) iter.next();
                sb.append("\n").append(property.genColumn());
            }
            sb.append("\n").append("</declare>");
            
            //declare和layout一起保存到了layout字段里（一张表只能有一个Long字段）
            tab.setLayout(sb.append("<layout>").append(tab.getLayout()).append("</layout></xform>").toString());
        }
        return tab;
    }
    
    public XFormTemplateTab saveXFormTemplateTab(XFormTemplateTab tab) {
        tab = (XFormTemplateTab) dao.create(tab);
        return tab;
    }
    
    public void deleteXFormTemplate(Long xTemplateId) {
        XFormTemplate template = (XFormTemplate) dao.getEntity(XFormTemplate.class, xTemplateId);
        List<?> tabIds = dao.getEntities("select o.id from XFormTemplateTab o where o.xformTemplateId = ?", template.getId());
        for(Iterator<?> it = tabIds.iterator(); it.hasNext();){
            deleteXFormTemplateTab((Long) it.next());
        }
        dao.delete(template);
    }

    @SuppressWarnings("unchecked")
    public void deleteXFormTemplateTab(Long tabId) {
        XFormTemplateTab tab = (XFormTemplateTab) dao.getEntity(XFormTemplateTab.class, tabId);
        List<?> relations = dao.getEntities("from PropertyTab o where o.id.tabId = ? ", tab.getId());
        dao.deleteAll((Collection<IEntity>) relations);
        dao.delete(tab);
    }

    public Object[] getXFormTempalteInfo(String entityCode, String xCode) {
        XFormTemplate xformTemplate = getXFormTemplateByCodeNoCache(entityCode, xCode);
        List<?> tabs = dao.getEntities("from XFormTemplateTab o where o.xformTemplateId = ? ", xformTemplate.getId());
        
        dao.evict(xformTemplate);
        for(Iterator<?> it = tabs.iterator(); it.hasNext();){
            dao.evict((XFormTemplateTab) it.next());
        }
        return new Object[]{tabs, getProperties(entityCode, false), xformTemplate};
    }

    public GridTemplate saveGridTemplate(GridTemplate gTemplate) {
        gTemplate = (GridTemplate) dao.create(gTemplate);
        //更新缓存
        String key = gTemplate.getEntityCode() + "_" + gTemplate.getCode();
        CacheManager.getInstance().getCachePool(CacheConstants.GRID_TEMPLATE_POOL).putObject(key, gTemplate);
        return gTemplate;
    }

    public void deleteGridTemplate(Long gTemplateId) {
        dao.delete(GridTemplate.class, gTemplateId);
    }

    public String getGridTemplateInfo(String entityCode, String gCode) {
        List<?> properties = getProperties(entityCode, false);
        StringBuffer sb = new StringBuffer("<declare>");
        for(Iterator<?> it = properties.iterator(); it.hasNext(); ){
            PropertyDef property = (PropertyDef) it.next();
            
            if(property.isSpare()) continue;
            
            sb.append("\n").append("<column name=\"").append(property.getKey()).append("\" caption=\"").append(property.getName());
            sb.append("\" mode=\"string\" editable=\"false\" align=\"center\"");
            if(property.getEditor().equals("2")) {
                sb.append(property.genEditor());
            }
            if(property.isHidden()) {
                sb.append(" display=\"none\" ");
            }
            sb.append("/>");                         
        }
        return sb.append("\n").append("</declare><data/>").toString();
    }

    public void importDynableEntity(String docXmlStr) {
        importDynableEntity(docXmlStr, DynableEntity.DYN_ROOT_ID);
    }
    
    public void importDynableEntity(String docXmlStr, Long groupId) {
        Element classNode = (Element) XMLDocUtil.dataXml2Doc(docXmlStr).selectSingleNode("/class");
        String entityCode = classNode.attributeValue("code");
        
        DynableEntity entity  = new DynableEntity();
        entity.setEntityCode(entityCode);
        entity.setParentId(groupId);
        entity.setName(classNode.attributeValue("name"));    
        entity.setClassName(classNode.attributeValue("className"));
        entity.setSeqNo(dao.getNextOrderByPId(entity.getParentId()));
        
        List<?> list = dao.getEntities("from DynableEntity o where o.entityCode = ?", entityCode);
        if(list != null && list.size() > 0)
            throw new BusinessException("相同实体代码的类型已经存在，请修改code后再保存。");
        
        entity = (DynableEntity) dao.create(entity);
        
        List<?> propertyNodes = classNode.selectNodes("//properties/property");
        for(Iterator<?> it = propertyNodes.iterator(); it.hasNext();){
            createPropertyDef(entityCode, entity, (Element)it.next()); //导入属性定义
        }
        
        List<?> spareProptertyNodes = XMLDocUtil.createDoc(DynConstants.SPARE_PROPERTIES)
                .selectSingleNode(DynConstants.SPARE_NODE_NAME).selectNodes("//properties/property");
        for(Iterator<?> it = spareProptertyNodes.iterator(); it.hasNext();){
            createPropertyDef(entityCode, entity, (Element)it.next()); //导入备用属性定义
        }
        
        Element xformTemplatesNode = (Element) classNode.selectSingleNode("//xformTemplates");
        for(Iterator<?> it = xformTemplatesNode.elementIterator("xformTemplate"); it.hasNext();){
            createXFormTemplate(entityCode, (Element)it.next()); //导入XFrom模板
        }
        Element gridTemplatesNode = (Element) classNode.selectSingleNode("//gridTemplates");
        for(Iterator<?> it = gridTemplatesNode.elementIterator("gridTemplate"); it.hasNext();){
            createGridTemplate(entityCode, (Element)it.next()); //导入grid模板
        }
    }

    private void createGridTemplate(String entityCode, Element gridTemplateNode) {
        GridTemplate grid = new GridTemplate();   
        BeanUtil.setDataToBean(grid, XMLDocUtil.dataNode2Map(gridTemplateNode));
        grid.setEntityCode(entityCode);
        String defaultTemplatePath = gridTemplateNode.attributeValue("defaultTemplatePath");
        if(defaultTemplatePath != null)
            grid.setDeclare(XMLDocUtil.createDoc(defaultTemplatePath).selectSingleNode("//grid/declare").asXML());
        dao.create(grid);
    }

    private void createXFormTemplate(String entityCode, Element xformTemplateNode) {
        XFormTemplate xform = new XFormTemplate();   
        BeanUtil.setDataToBean(xform, XMLDocUtil.dataNode2Map(xformTemplateNode));
        xform.setEntityCode(entityCode);
        xform = (XFormTemplate) dao.create(xform);
        
        for(Iterator<?> iter = xformTemplateNode.elementIterator("tab"); iter.hasNext();){
            Element tabNode = (Element)iter.next();
            XFormTemplateTab tab = new XFormTemplateTab();          
            BeanUtil.setDataToBean(tab, XMLDocUtil.dataNodes2Map(tabNode));
            tab.setXformTemplateId(xform.getId());
            String defaultTemplatePath = tabNode.attributeValue("defaultTemplatePath");
            if(defaultTemplatePath != null)
                tab.setLayout(XMLDocUtil.createDoc(defaultTemplatePath).getRootElement().asXML());
            dao.create(tab);
        }
    }

    private void createPropertyDef(String entityCode, DynableEntity entity, Element propertyNode) {
        PropertyDef property = new PropertyDef();           
        BeanUtil.setDataToBean(property, XMLDocUtil.dataNodes2Map(propertyNode));
        property.setEntityCode(entityCode);
        property.setEntityName(entity.getClassName());
        property.setIsdyn(new Integer(0));
        if(property.getKey().startsWith("spare")){
            property.setIsSpare(new Integer(1));
        }
        property.setSeqNo(dao.getNextSeqNo(entityCode));
        dao.create(property);
    }

    public void deleteDynableEntity(String entityCode) {
        DynableEntity entity = getDynableEntity(entityCode);
        
        List<?> properties = getProperties(entityCode, false);
        for(Iterator<?> it = properties.iterator(); it.hasNext(); ){
            PropertyDef property = (PropertyDef) it.next();
            //如果是动态属性，则先删除动态属性值
            if(property.isdyn()){
                dao.deleteAll(dao.getEntities("from PropertyEntry o where o.defId = ?", property.getId()));
            }
        }       
 
        List<?> tabIds = dao.getEntities("select o.id from XFormTemplateTab o, XFormTemplate t " +
                " where o.xformTemplateId = t.id and t.entityCode = ? ", entityCode);
        for(Iterator<?> it = tabIds.iterator(); it.hasNext();){
            deleteXFormTemplateTab((Long) it.next());
        }
        
        dao.deleteAll(dao.getEntities("from GridTemplate o where o.entityCode = ? ", entityCode));
        dao.deleteAll(dao.getEntities("from XFormTemplate o where o.entityCode = ? ", entityCode));
        dao.deleteAll(properties);
        dao.delete(entity);
    }

    public void copyDynableEntity(String entityCode, String newEntityCode) {
        DynableEntity entity = getDynableEntity(entityCode);
        dao.evict(entity);
        entity.setId(null);
        entity.setEntityCode(newEntityCode);
        entity.setName("副本_" + entity.getName());
        entity = (DynableEntity) dao.create(entity);
        
        List<PropertyDef> properties = getProperties(entityCode, false);
        Map<Long, Long> old2new = new HashMap<Long, Long>();
        for(PropertyDef property : properties){
            Long oldPropertyId = property.getId();
            dao.evict(property);
            property.setId(null);
            property.setEntityCode(newEntityCode);
            property = (PropertyDef) dao.create(property);
            old2new.put(oldPropertyId, property.getId());
        }
        // 复制模板信息
        List<?> list = dao.getEntities("from XFormTemplate o where o.entityCode = ? ", entityCode);
        for(Iterator<?> it = list.iterator();it.hasNext();){
            XFormTemplate template = (XFormTemplate) it.next();
            List<?> tabs = dao.getEntities("from XFormTemplateTab o where o.xformTemplateId = ? ", template.getId());
            dao.evict(template);
            template.setId(null);
            template.setEntityCode(newEntityCode);
            template = (XFormTemplate) dao.create(template);
            for(Iterator<?> ite = tabs.iterator();ite.hasNext();){
                XFormTemplateTab tab = (XFormTemplateTab) ite.next();
                List<?> relations = dao.getEntities("from PropertyTab o where o.id.tabId = ? ", tab.getId());
                dao.evict(tab);
                tab.setId(null);
                tab.setXformTemplateId(template.getId());
                tab = (XFormTemplateTab) dao.create(tab);
                for(Iterator<?> iter = relations.iterator();iter.hasNext();){
                    PropertyTab pt = (PropertyTab) it.next();
                    pt.getId().setTabId(tab.getId());
                    pt.getId().setDefId((Long) old2new.get(pt.getId().getDefId()));
                    dao.create(pt);
                }
            }
        }
        list = dao.getEntities("from GridTemplate o where o.entityCode = ? ", entityCode);
        for(Iterator<?> it = list.iterator();it.hasNext();){
            GridTemplate template = (GridTemplate) it.next();
            dao.evict(template);
            template.setId(null);
            template.setEntityCode(newEntityCode);
            dao.create(template);
        }
    }

    public void updateDynableEntityName(String entityCode, String newName) {
        DynableEntity entity = getDynableEntity(entityCode);
        entity.setName(newName);
        dao.create(entity);
    }

    public Map<String, String> getXFormTemplate(String entityCode, String xCode) { //（远程）
        XFormTemplate template = getXFormTemplateByCode(entityCode, xCode);
        
        List<?> tabs = dao.getEntities("from XFormTemplateTab o where o.xformTemplateId = ?", template.getId());
        Map<String, String> tabsMap = new HashMap<String, String>();
        for(Iterator<?> it = tabs.iterator(); it.hasNext();){
            StringBuffer sb = new StringBuffer();
            XFormTemplateTab tab = (XFormTemplateTab) it.next();
            
            sb.append("<xform>").append(tab.getDeclare()).append("<layout>").append(tab.getLayoutOnly()).append("</layout><data ");
            
            List<?> properties = dao.getEntities("select p from PropertyDef p, PropertyTab o " +
                    "where p.id = o.id.defId and o.id.tabId = ? ", tab.getId());
            
            Map<String, Object> defaultValues = new HashMap<String, Object>();
            for(Iterator<?> iter = properties.iterator(); iter.hasNext();){
                PropertyDef property = (PropertyDef) iter.next();
                //将动态属性特殊放入data节点，以利于提交数据时可以设置到AbstractDynEntity.dynpropertiesMap中
                if(property.isdyn()){
                    sb.append(property.getKey()).append("=\"").append(property.genDynKey()).append("\" ");
                }
                //如果属性有默认值，则加载
                if(property.getDefaultValue() != null){
                    defaultValues.put(property.getKey(), property.getDefaultValue());
                } 
            }
            sb.append(">").append(XMLDocUtil.map2DataNode(defaultValues, "row").asXML()).append("</data></xform>");
            tabsMap.put(tab.getCode(), sb.toString());
        }
        return tabsMap;
    }

    public String getGridTemplate(String entityCode, String gCode) { //（远程）
        GridTemplate template = getGridTemplateByCode(entityCode, gCode);
        if(template.getDeclare() == null){
            List<?> properties = getProperties(entityCode, false);
            StringBuffer sb = new StringBuffer("<declare>");
            for(Iterator<?> it = properties.iterator(); it.hasNext(); ){
                PropertyDef property = (PropertyDef) it.next();
                
                if(property.isSpare()) continue;
                
                sb.append("\n").append("<column name=\"").append(property.getKey());
                sb.append("\" caption=\"").append(property.getName());
                sb.append("\" mode=\"string\" editable=\"false\" align=\"center\"");
                if(property.getEditor().equals("2"))//2为下拉列表
                    sb.append(property.genEditor());
                if(property.isHidden())
                    sb.append(" display=\"none\" ");
                sb.append("/>");                         
            }
            template.setDeclare(sb.append("\n").append("</declare>").toString());
        }
        return "<grid version=\"2\">" + template.getDeclare() + "<data/></grid>";
    }

    @SuppressWarnings("unchecked")
    public List<PropertyDef> getProperties(String entityCode, boolean isOnlyDyn) {
        String hql = "from PropertyDef o where o.entityCode = ?" 
            + (isOnlyDyn ? " and o.isdyn = 1 " : "")  + " order by o.seqNo";

        return (List<PropertyDef>) dao.getEntities(hql, entityCode);
    }

    public void copyProperties(String[] ids, String entityCode) {
        for(int i = 0; i < ids.length; i++){
            PropertyDef def = (PropertyDef) dao.getEntity(PropertyDef.class, Long.valueOf(ids[i]));
            dao.evict(def);
            def.setId(null);
            def.setIsdyn(new Integer(1));
            def.setEntityCode(entityCode);
            saveProperty(def);
        }
    }
    
    /**
     * 根据code值获取对应的动态实体对象
     * @param entityCode
     * @return
     */
    public DynableEntity getDynableEntity(String entityCode) throws BusinessException{
        List<?> list = dao.getEntities("from DynableEntity o where o.entityCode = ?", entityCode);
        if(list.size() == 0) {
            throw new BusinessException("实体代码有误，找不到相应动态属性实体。");
        }
        
        return (DynableEntity)list.get(0);
    }
    
    /**
     * 根据动态实体的code值和XForm模板的code值获取对象XForm模板
     * @param entityCode
     * @param xCode
     * @return
     */
    public XFormTemplate getXFormTemplateByCode(String entityCode, String xCode) throws BusinessException{
        IPool pool = CacheManager.getInstance().getCachePool(CacheConstants.XFORM_TEMPLATE_POOL);
        String key = entityCode + "_" + xCode;
        Cacheable item = pool.getObject(key);
        if(item != null) {
            return (XFormTemplate) item.getValue();
        }
        
        XFormTemplate template = getXFormTemplateByCodeNoCache(entityCode, xCode);
        
        pool.putObject(key, template);
        return template;
    }
    
    private XFormTemplate getXFormTemplateByCodeNoCache(String entityCode, String xCode) throws BusinessException{
        List<?> list = dao.getEntities("from XFormTemplate o where o.entityCode = ? and o.code = ? ", entityCode, xCode);
        if(list.isEmpty()) {
            throw new BusinessException("根据(entityCode：" + entityCode + "，code：" + xCode + ")找不到相应的xform模板，" +
                    "请检查两code值是否有误，或者模板是否已经生成！");
        }
        
        return (XFormTemplate) list.get(0);
    }
    
    /**
     *  根据动态实体的code值和Grid模板的code值获取对象Grid模板
     * @param entityCode
     * @param gCode
     * @return
     * @throws BusinessException
     */
    public GridTemplate getGridTemplateByCode(String entityCode, String gCode) throws BusinessException{
        IPool pool = CacheManager.getInstance().getCachePool(CacheConstants.GRID_TEMPLATE_POOL);
        String key = entityCode + "_" + gCode;
        Cacheable item = pool.getObject(key);
        if(item != null) {
            return (GridTemplate) item.getValue();
        }
        
        List<?> list = dao.getEntities("from GridTemplate o where o.entityCode = ? and o.code = ? ", entityCode, gCode);
        if(list.isEmpty()) {
            throw new BusinessException("根据(entityCode：" + entityCode + "，code：" + gCode + ")找不到相应的grid模板，" +
                    "请检查两code值是否有误，或者模板是否已经生成！");
        }
        
        GridTemplate template = (GridTemplate) list.get(0);
        pool.putObject(key, template);
        return template;
    }
    
    public Object getEntity(Class<?> clazz, Long id) {
        return dao.getEntity(clazz, id);
    }
}

